package com.party.mobile.web.interceptor;

import com.party.common.redis.StringJedis;
import com.party.common.utils.StringUtils;
import com.party.common.utils.UUIDUtils;
import com.party.mobile.web.annotation.SessionToken;
import com.party.mobile.web.dto.AjaxResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedWriter;
import java.io.OutputStreamWriter;
import java.lang.reflect.Method;
import java.util.*;

/**
 * @Author: yifeng
 * @Date: 2018/11/30 13:48
 * @Description: 防重复提交的拦截器
 */
@Component(value = "tokenInterceptor")
public class TokenInterceptor extends HandlerInterceptorAdapter {

    static final String TOKEN = "sessionToken";
    static final String KEY = "sessionKey";

    @Autowired
    private StringJedis stringJedis;

    Logger logger = LoggerFactory.getLogger(getClass());

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (handler instanceof HandlerMethod) {
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            Method method = handlerMethod.getMethod();
            SessionToken annotation = method.getAnnotation(SessionToken.class);
            if (annotation != null) {
                boolean needRemoveSession = annotation.verify();
                if (needRemoveSession) {
                    if (isRepeatSubmit(request)) {
                        response.setStatus(HttpServletResponse.SC_FORBIDDEN);
                        response.setContentType(MediaType.APPLICATION_JSON_VALUE);
                        BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(response.getOutputStream()));
                        writer.write("sessionToken not match");
                        writer.close();
                        return false;
                    }
                }
            }
            return true;
        } else {
            return super.preHandle(request, response, handler);
        }
    }

    private boolean isRepeatSubmit(HttpServletRequest request) {
        try {
            logger.info("进来----准备验证------");
            String sessionKey = request.getHeader(KEY);
            if (StringUtils.isEmpty(sessionKey)) {
                logger.info("111111111111  sessionKey 为空");
                return false;
            }

            String decodeSessionKey = null;
            try {
                byte[] asBytes = Base64.getDecoder().decode(sessionKey);
                decodeSessionKey = new String(asBytes);
            } catch (Exception e) {
                logger.info("22222222 sessionKey解码异常：sessionKey：{}", sessionKey);
                return false;
            }
            if (StringUtils.isNotEmpty(decodeSessionKey)) {
                String serverToken = stringJedis.getValue(TOKEN + "_" + sessionKey);
                if (StringUtils.isEmpty(serverToken)) {
                    logger.info("3333333  服务端token 为空");

                    stringJedis.delete(TOKEN + "_" + sessionKey);

                    return true;
                }

                String clientToken = request.getHeader(TOKEN);
                if (StringUtils.isNotEmpty(clientToken) && !serverToken.equals(clientToken)) {
                    stringJedis.delete(TOKEN + "_" + sessionKey);
                    logger.info("4444444  客户端token不匹配------clientToken：{}-------serverToken：{}", clientToken, serverToken);
                    return true;
                }
                stringJedis.delete(TOKEN + "_" + sessionKey);
            }
        } catch (Exception e) {
            logger.error("验证token异常", e);
        }
        return false;
    }

    public void getToken(AjaxResult ajaxResult) {
        try {
            String sessionToken = UUIDUtils.generateRandomUUID();
            ajaxResult.setSessionToken(sessionToken);

            String key = (sessionToken + new Random().nextInt(99999)).substring(0, 15);
            List<String> list = Arrays.asList(key.split(""));
            Collections.reverse(list);
            String join = StringUtils.join(list.toArray(), "");
            String sessionKey = Base64.getEncoder().encodeToString(join.getBytes());
            ajaxResult.setSessionKey(sessionKey);

            stringJedis.setValue(TOKEN + "_" + sessionKey, sessionToken, 3600);
        } catch (Exception e) {
            logger.error("生成key和token异常", e);
            ajaxResult.setSessionToken(null);
            ajaxResult.setSessionKey(null);
        }
    }
}
